
#include <BRender>
#include <BViewer>
#include <BPainter>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BStyle>
#include <BSystem>

#include "DrawCapsuleHandler.h"

DrawCapsuleHandler::DrawCapsuleHandler(BHandler* parent) : BHandler(parent)
{
	_vertexPicker = new AdsorbVertexPicker();
	_edgePicker = new EdgePicker();

	connect(this, Signal_AssetChanged, &DrawCapsuleHandler::slotAssetChanged);
	connect(this, Signal_PropertyChanged, &DrawCapsuleHandler::slotPropertyChanged);

}
DrawCapsuleHandler::~DrawCapsuleHandler()
{

}

void DrawCapsuleHandler::slotAssetChanged(BObject* object, const BValue& value)
{
	Target* target = value;
	this->setEnabled(target);
}
void DrawCapsuleHandler::slotPropertyChanged(BObject* object, const BValue& value)
{

}

void DrawCapsuleHandler::attached(BViewer* viewer)
{
	Target* target = this->asset();
	if (BShape* shape = target->shape())
	{
		_capsule = dynamic_cast<BCapsule*>(shape);
	}
	_vertexPicker->setCamera(this->camera());
	_edgePicker->setCamera(this->camera());
	if (const BStyle* style = this->viewer()->realStyle())
	{
		_dragImage = style->image("drag");
	}
	_dragImage = 0;
	_hoveredIndex = -1;
	_vertices.clear();
}
void DrawCapsuleHandler::detached(BViewer* viewer)
{
	_capsule = 0;
	_vertexPicker->setCamera(0);
	_edgePicker->setCamera(0);
	_dragImage = 0;
	_vertices.clear();
	_hoveredIndex = -1;
}

void DrawCapsuleHandler::paint(BPainter& painter)
{
	if (_hoveredHit)
	{
		const BVector& vertex = _hoveredHit->absolutePoint();
		BPoint pos = this->viewer()->point(vertex);
		painter.drawImage(pos, _dragImage, Align_Center);
	}
	if (_vertices.size())
	{
		painter.setColor(Color_Text);
		painter.drawText(this->viewer()->centerRect(), _vertices.size(), Align_LeftBottom);
	}
}
void DrawCapsuleHandler::render(BRender& render)
{
	render.setLighting(false);
	render.setDepthTest(false);

	if (_hoveredHit)
	{
		BVector point = _hoveredHit->absolutePoint();
		render.setPointSize(6);
		render.setPointSmooth(true);
		render.drawVertex(point);
	}

	{
		render.setPointSize(6);
		render.setPointSmooth(true);
		render.setColor(200, 0, 200);
		render.drawVertex(_point);
	}

	render.setDepthOffset(-1);
	render.setColor(200, 0, 0);
	render.drawVertices(_vertices);
	render.setDepthOffset(0);
}

void DrawCapsuleHandler::updateEvent(const BEvent& event)
{

}
void DrawCapsuleHandler::styleEvent(const BEvent& event)
{
	if (const BStyle* style = event.value())
	{
		_dragImage = style->image("drag");
	}
}
void DrawCapsuleHandler::freshEvent(const BEvent& event)
{

}

void DrawCapsuleHandler::keyPressEvent(const BKeyEvent& keyEvent)
{
	if (keyEvent.key() == Key_Enter)
	{
		this->detach();
		keyEvent.accept();
	}
	if (keyEvent.key() == Key_Back)
	{
		_vertices.pop();
		this->emit(Signal_Changed);
		this->fresh();
		keyEvent.accept();
	}
	if (keyEvent.key() == Key_Delete)
	{
		this->fresh();
		keyEvent.accept();
	}
	if (keyEvent.key() == Key_Escape)
	{
		if (_capsule)
		{
			Target* target = this->asset();
			if (BNode* node = target->node())
			{
				node->removeShape(_capsule);
			}
			else if (BGroup* group = target->group())
			{
				group->remove(_capsule);
			}
			else if (BScene* scene = target->scene())
			{
				scene->remove(_capsule);
			}
		}
		this->detach();
		keyEvent.accept();
	}
}
void DrawCapsuleHandler::keyReleaseEvent(const BKeyEvent& keyEvent)
{

}

void DrawCapsuleHandler::mouseEnterEvent(const BMouseEvent& mouseEvent)
{

}
void DrawCapsuleHandler::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{

}
void DrawCapsuleHandler::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		if (_hoveredHit && _vertices.empty())
		{
			BVector point = _hoveredHit->absolutePoint();
			BVector normal = _hoveredHit->absoluteNormal();
			_vertices.append(point);
			_baseLine.set(point, point + normal);
			_basePlane.set(normal, point);
			_capsule = new BCapsule();
			Target* target = this->asset();
			if (BNode* node = target->node())
			{
				node->insertShape(_capsule);
				BMatrix matrix = node->matrix().inverse();
				_capsule->setPosition(point * matrix);
				_capsule->setRotate(BQuater(BVector(0, 0, 1), normal * matrix));
			}
			else if (BGroup* group = target->group())
			{
				group->insert(_capsule);
				_capsule->setPosition(point);
				_capsule->setRotate(BQuater(BVector(0, 0, 1), normal));
			}
			else if (BScene* scene = target->scene())
			{
				scene->insert(_capsule);
				_capsule->setPosition(point);
				_capsule->setRotate(BQuater(BVector(0, 0, 1), normal));
			}
			_hoveredHit = 0;
			this->fresh();
			mouseEvent.accept();
		}
		if (_vertices.size() == 1)
		{
			_vertices.append(_point);
			this->fresh();
			mouseEvent.accept();
		}
		if (_vertices.size() == 2)
		{
			_vertices.append(_point);
			this->fresh();
			mouseEvent.accept();
		}
	}
}
void DrawCapsuleHandler::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		this->fresh();
		mouseEvent.accept();
	}
}
void DrawCapsuleHandler::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	BCamera* camera = this->camera();
	const BPoint& pos = mouseEvent.pos();
	BLine line = this->viewer()->line(pos);
	if (mouseEvent.button() == Button_None)
	{
		if (_vertices.empty())
		{
			_vertexPicker->setLine(line);
			_hoveredHit = _vertexPicker->apply(this->scene());
			this->fresh();
		}
		else if (_vertices.size() == 1)
		{
			if (line.intersect(_basePlane, _point))
			{
				BReal radius = (_point - _vertices[0]).length();
				_capsule->setRadius(radius);
				this->fresh();
			}
		}
		else if (_vertices.size() == 2)
		{
			_point = _baseLine.closest(line);
			BReal height = (_point - _vertices[0]).length();
			_capsule->setHeight(height * 2);
			this->fresh();
		}
		mouseEvent.accept();
	}
}
